package com.snail.service.Impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.MultiMatchQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import com.snail.mapper.ResultMapper;
import com.snail.model.dto.SearchResultDTO;
import com.snail.model.entity.Product;
import com.snail.model.pojo.Result;
import com.snail.model.pojo.SearchHitResult;
import com.snail.service.BizSearchService;
import com.snail.service.HotdataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


@Service
public  class BizSearchServiceImpl implements BizSearchService {
    @Autowired
    ResultMapper resultMapper;
    @Autowired
    HotdataService hotdataService;
    @Autowired
    private ElasticsearchClient elasticsearchClient;

    @Override
    public SearchHitResult<Result> findByNameContaining(String keyword) {

        return hotdataService.queryHotData(keyword,SearchHitResult.class, this::searchAndTransform);

    }

    @Override
    public SearchHitResult searchAndTransform(String keyword){
        SearchHitResult<Result> res=SearchHitResult.<Result>fromSearchHits( this.searchProductsByClient(keyword,1,10));
        return res;
    }

    @Override
    public SearchResponse<Result> searchProductsByClient(String keyword, int page, int size) {
    try {
        return elasticsearchClient.search(s -> s
                        .index("woniumall")
                        .query(q -> q
                                .match(m -> m.field("name").query(keyword))
                        ).from((page - 1) * size) // 起始位置 (offset)
                        .size(size),              // 每页条数,
                Result.class // 指定返回的文档类型
        );
    } catch (IOException e) {

        throw new RuntimeException("搜索失败", e);
    }
}

    @Override
    public SearchResponse<Product> searchProduct(String keyword, int page, int size) {
        try {
            return elasticsearchClient.search(s -> s
                            .index("biz_product")
                            .query(q -> q
                                    .match(m -> m.field("product_name").query(keyword))
                            ).from((page - 1) * size) // 起始位置 (offset)
                            .size(size),              // 每页条数,
                    Product.class // 指定返回的文档类型
            );
        } catch (IOException e) {
            throw new RuntimeException("搜索失败", e);
        }
    }

    @Override
    public List<SearchResultDTO> searchAll(String keyword) throws IOException {
        // 构造 multi_match 查询（关键词部分）
        Query keywordQuery = MultiMatchQuery.of(m -> m
                .query(keyword)
                .fields(
                        // sys_user
                        "username", "nickname", "email", "phone",
                        // biz_works
                        "works_name", "description",
                        // biz_product
                        "product_name", "description",
                        // biz_collection
                        "name", "description"
                )
        )._toQuery();

        // 构造 bool 查询，结合关键词和过滤条件
        Query finalQuery = BoolQuery.of(b -> b
                .must(keywordQuery)
                .filter(f -> f
                        .bool(fb -> fb
                                // deleted = 0（biz_collection 无此字段，所以只对其它索引起作用）
                                .should(s -> s
                                        .bool(bb -> bb
                                                .mustNot(mn -> mn.exists(e -> e.field("deleted"))) // 没有 deleted 字段的文档也能通过
                                        )
                                )
                                .should(s -> s
                                        .term(t -> t.field("deleted").value(0))
                                )
                                .minimumShouldMatch("1") // 至少满足一个 should
                        )
                )
                .filter(f -> f
                        .bool(fb -> fb
                                // biz_works status=3
                                .should(s -> s
                                        .bool(bb -> bb
                                                .must(m -> m.term(t -> t.field("status").value(3)))
                                                .filter(m -> m.term(t -> t.field("type").value("biz_works"))) // 仅限 works 索引文档
                                        )
                                )
                                // biz_product status=1
                                .should(s -> s
                                        .bool(bb -> bb
                                                .must(m -> m.term(t -> t.field("status").value(1)))
                                                .filter(m -> m.term(t -> t.field("type").value("biz_product"))) // 仅限 product 索引文档
                                        )
                                )
                                // 其它索引不限制 status
                                .should(s -> s
                                        .bool(bb -> bb
                                                .mustNot(m -> m.exists(e -> e.field("status")))
                                        )
                                )
                        )
                )
        )._toQuery();

        // 构建搜索请求
        SearchRequest request = SearchRequest.of(s -> s
                .index("sys_user", "biz_product", "biz_works", "biz_collection")
                .query(finalQuery)
                .size(50)
                .sort(sort -> sort.score(o -> o.order(SortOrder.Desc)))
                .source(src -> src
                        .filter(f -> f
                                .includes("*", "type")
                                .excludes("@version", "@timestamp")
                        )
                )
        );

        // 执行搜索
        SearchResponse<Map> response = elasticsearchClient.search(request, Map.class);

        List<SearchResultDTO> resultList = new ArrayList<>();
        for (Hit<Map> hit : response.hits().hits()) {
            Map<String, Object> source = hit.source();

            SearchResultDTO dto = new SearchResultDTO();
            dto.setIndex(hit.index());
            dto.setType((String) source.get("type"));
            dto.setScore(hit.score() != null ? hit.score().floatValue() : 0f);
            dto.setData(source);

            resultList.add(dto);
        }

        return resultList;
    }

}
